package com.gimi.cloud.bbp.manage.service.sys.impl;

import com.alibaba.fastjson.JSONObject;
import com.gimi.cloud.bbp.common.constant.RedisKeyConstant;
import com.gimi.cloud.bbp.common.enums.ResponseCodeEnum;
import com.gimi.cloud.bbp.common.exception.MsgException;
import com.gimi.cloud.bbp.common.jwt.Jwt;
import com.gimi.cloud.bbp.common.utils.MD5;
import com.gimi.cloud.bbp.common.utils.ReflectUtils;
import com.gimi.cloud.bbp.common.utils.StringUtil;
import com.gimi.cloud.bbp.commonService.redis.RedisService;
import com.gimi.cloud.bbp.dao.dao.sys.SysMasterDao;
import com.gimi.cloud.bbp.dao.dao.sys.SysMasterRoleDao;
import com.gimi.cloud.bbp.dao.myMapper.core.query.QueryParam;
import com.gimi.cloud.bbp.dto.sys.SysMasterDTO;
import com.gimi.cloud.bbp.dto.sys.SysMenuDTO;
import com.gimi.cloud.bbp.entity.sys.SysMasterEntity;
import com.gimi.cloud.bbp.entity.sys.SysMasterRoleEntity;
import com.gimi.cloud.bbp.manage.service.sys.SysMasterService;
import com.gimi.cloud.bbp.manage.service.sys.SysMenuService;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 后台管理员相关接口实现类
 *
 * @author wbj
 * @version 1.0
 * @Description
 * @create 2018-01-24
 **/
@Service
public class SysMasterServiceImpl implements SysMasterService{
    private static final Logger logger = LoggerFactory.getLogger(SysMasterServiceImpl.class);
    private SysMasterDao sysMasterDao;
    private RedisService redisService;
    private SysMenuService sysMenuService;
    private SysMasterRoleDao sysMasterRoleDao;

    @Autowired
    public SysMasterServiceImpl(SysMasterDao sysMasterDao, RedisService redisService, SysMenuService sysMenuService, SysMasterRoleDao sysMasterRoleDao) {
        this.sysMasterDao = sysMasterDao;
        this.redisService = redisService;
        this.sysMenuService = sysMenuService;
        this.sysMasterRoleDao = sysMasterRoleDao;
    }

    @Override
    public List<SysMasterDTO> queryList(SysMasterDTO dto, boolean isPaging) throws Exception {
        if(isPaging){
            PageHelper.startPage(dto.getPageNums(),dto.getPageSizes());
        }
        String sql ="SELECT mas.*,GROUP_CONCAT(role.ro_name) roleNames,GROUP_CONCAT(role.ro_id)roleIds" +
                " FROM sys_master mas " +
                " LEFT JOIN sys_master_role mr ON mr.ma_id = mas.ma_id" +
                " LEFT JOIN sys_role role ON role.ro_id = mr.ro_id AND role.is_delete = 0" +
                " WHERE mas.is_delete = 0 AND mas.ma_name LIKE '%'||:maName||'%'" +
                " GROUP BY mas.ma_id";
        QueryParam queryParam = new QueryParam();
        queryParam.setSql(sql);
        queryParam.setParamObject(dto);
        return sysMasterDao.selectListDTOBySql(queryParam);
    }

    @Override
    public SysMasterDTO load(SysMasterDTO dto, Object id) throws Exception {
        SysMasterEntity masterEntity = sysMasterDao.queryBy("ma_id",id);
        if(null == masterEntity){
            return null;
        }
        SysMasterDTO masterDTO = new SysMasterDTO();
        ReflectUtils.copyPropertiesIgnoreNull(masterEntity,masterDTO);
        return masterDTO;
    }

    @Override
    public SysMasterDTO saveOrUpdate(SysMasterDTO dto) throws Exception {
        SysMasterEntity masterEntity = null;
        if(null != dto.getMaId()){
            masterEntity = sysMasterDao.queryBy("ma_id",dto.getMaId());
            if(null == masterEntity){
                throw new MsgException(ResponseCodeEnum.NO_DATA,"未获取主键为" + dto.getMaId() + "的管理员信息，修改失败");
            }
        }else{
            masterEntity = new SysMasterEntity();
        }
        if(!dto.getPassword().equals(masterEntity.getPassword())){
            dto.setPassword(MD5.toMD5(dto.getPassword()));
        }
        ReflectUtils.copyPropertiesIgnoreNull(dto, masterEntity);
        if(StringUtils.isNotBlank(masterEntity.getUsername())){
            int existCount = 0;
            if(null == masterEntity.getMaId()){
                existCount = sysMasterDao.queryCountBy("username", masterEntity.getUsername());
            }else{
                existCount = sysMasterDao.queryCountByExclude("username", masterEntity.getUsername(), "ma_id", masterEntity.getMaId());
            }
            if(existCount>0){
                throw new MsgException(ResponseCodeEnum.ERR_USERNAME_USED,"已存在登录名为"+masterEntity.getUsername()+"的管理员");
            }
        }
        if (null != dto.getMaId()) {
            sysMasterDao.baseUpdateByPrimaryKey(masterEntity);
        } else {
            sysMasterDao.baseInsert(masterEntity);
        }
        ReflectUtils.copyPropertiesIgnoreNull(masterEntity, dto);
        //用户授权
        this.bindRole(dto,dto.getRoleIds());
        return dto;
    }

    @Override
    public int delete(SysMasterDTO dto, Object id, boolean realDel) throws Exception {
        SysMasterEntity master = sysMasterDao.queryBy("ma_id", id);
        if (null == master) {
            throw new MsgException(ResponseCodeEnum.PARAMETER_EXCEPTION, "未获取到主键为" + id + "的管理员信息,删除失败");
        }
        // 非物理删除
        if (!realDel) {
            ReflectUtils.copyPropertiesIgnoreNullAndEmptyStr(dto, master);
            master.setIsDelete(1);
            return sysMasterDao.baseUpdateByPrimaryKey(master);
        }
        return sysMasterDao.deleteByPrimaryKey(id);
    }

    @Override
    public SysMasterDTO queryMasterByUsername(SysMasterDTO dto, String username) throws Exception {
        SysMasterEntity master = sysMasterDao.queryBy("username", username);
        if(null == master){
            return null;
        }
        SysMasterDTO masterDTO = new SysMasterDTO();
        ReflectUtils.copyPropertiesIgnoreNullAndEmptyStr(master,masterDTO);
        return masterDTO;
    }

    @Override
    public String createTokenAndSet2Redis(SysMasterDTO masterDTO) {
        JSONObject masterTokenRule = redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_MANAGE_USER_TOKEN_RULE);
        if(null == masterTokenRule){
            logger.error("生成管理员登录token失败，未获取到登录token配置信息");
            return null;
        }
        String redisKey = RedisKeyConstant.MANAGE_LOGIN_MASTER_TOKEN_PREFIX +masterDTO.getUsername();
        List<String> masterTokens = null;
        //非单一登录限制
        if(!"1".equals(masterTokenRule.getString("is_single_login"))){
            //获取系统中存在的登录token
            masterTokens = redisService.getList(redisKey,String.class);
        }
        if(null == masterTokens){
            masterTokens = new ArrayList<>();
        }
        Map<String, Object> validResult;
        //使用HashSet，避免重复生成token
        HashSet<String> masterNewTokens = new HashSet<>();
        for(String tempToken:masterTokens){
            validResult = Jwt.validToken(tempToken,masterTokenRule.getString("jwt_token_secret"));
            //如果当前状态是有效的token则保留该token
            if(null != validResult && null != validResult.get("state") && "VALID".equals(validResult.get("state").toString())){
                masterNewTokens.add(tempToken);
            }
        }
        masterTokens.clear();
        //设置当前用户的token为有效的token
        masterTokens.addAll(masterNewTokens);
        Map<String,Object> payload = new HashMap<>(3);
        payload.put("maId",masterDTO.getMaId());
        payload.put("userName",masterDTO.getUsername());
        //过期时间
        payload.put("ext", System.currentTimeMillis() + masterTokenRule.getLong("validate_times"));
        String token = Jwt.createToken(payload,masterTokenRule.getString("jwt_token_secret"));
        masterTokens.add(token);
        redisService.setList(redisKey,masterTokens);
        return token;
    }

    @Override
    public Map<String, Object> getMasterPermissions(SysMasterDTO sysMasterDTO, Integer masterId) throws Exception {
        Map<String,Object> masterPermissions = new HashMap<>();
        SysMenuDTO sysMenuDTO = new SysMenuDTO();
        ReflectUtils.copyPropertiesIgnoreNull(sysMasterDTO, sysMenuDTO);
        List<SysMenuDTO> menus = sysMenuService.getMenuByMasterId(sysMenuDTO,masterId);
        //用户的菜单权限
        masterPermissions.put("authMenus",sysMenuService.menuToTree(menus));
        Map<String,Object> permissions =sysMenuService.getPermissions(sysMenuDTO,menus);
        //添加权限信息
        masterPermissions.putAll(permissions);
        return masterPermissions;
    }

    @Override
    public SysMasterDTO findMasterById(SysMasterDTO sysMasterDTO, Integer maId) throws Exception {
        return sysMasterDao.findMasterById(maId);
    }

    @Override
    public int bindRole(SysMasterDTO dto, String roIds) throws Exception {
        sysMasterRoleDao.deleteByMaId(dto.getMaId());
        if(StringUtil.isNotBlank(roIds)){
            List<SysMasterRoleEntity> sysMasterRoleEntities= new ArrayList<>();
            for(String roId:roIds.split(",")){
                SysMasterRoleEntity masterRoleEntity = new SysMasterRoleEntity();
                ReflectUtils.copyPropertiesIgnoreNullAndEmptyStr(dto,masterRoleEntity);
                masterRoleEntity.setMaId(dto.getMaId());
                masterRoleEntity.setRoId(Integer.valueOf(roId));
                masterRoleEntity.setMrCreated(new Date());
                sysMasterRoleEntities.add(masterRoleEntity);
            }
            return  sysMasterRoleDao.insertList(sysMasterRoleEntities);
        }
        return 0;
    }
}
